#include <iostream>
#include <string>
#include <memory>

using std::cout;
using std::endl;
using std::string;
using std::unique_ptr;

class RaiseRequest{
public:
    RaiseRequest(const string &name,int salary)
    :_name(name)
     ,_salary(salary)
    {

    }

    string getName() const{
        return _name;
    }
    int getSalary() const{
        return _salary;
    }

    ~RaiseRequest(){}
private:
    string _name;
    int _salary;
};

class SalaryApprover{
public:
    SalaryApprover()
        :_pChain(nullptr)
    {

    }

    void setNestChain(SalaryApprover * pChain)
    {
        _pChain = pChain;
    }

    void sendRequestTONextHandler(const RaiseRequest &req){
        if(_pChain){
            _pChain->processRequest(req);
        }
        else{
            cout << req.getName() << "加薪 " << req.getSalary() 
                 << " 不通过" << endl;
        }
    }
    virtual void processRequest(const RaiseRequest &req) = 0;
private:
    SalaryApprover * _pChain;
};

class DM
:public SalaryApprover 
{
public:
    void processRequest(const RaiseRequest &req){
        if(req.getSalary() < 1000){
            cout << req.getName() << "加薪 " 
                 << req.getSalary() << " DM通过"
                 << endl;
        }else{
            sendRequestTONextHandler(req);
        }
    }
};


class CTO
:public SalaryApprover 
{
public:
    void processRequest(const RaiseRequest &req){
        if(req.getSalary() > 1000 && req.getSalary() < 5000){
            cout << req.getName() << "加薪 " 
                 << req.getSalary() << " CTO通过"
                 << endl;
        }else{
            sendRequestTONextHandler(req);
        }
    }
};



class GM
:public SalaryApprover 
{
public:
    void processRequest(const RaiseRequest &req){
        if(req.getSalary() > 5000 && req.getSalary() < 15000){
            cout << req.getName() << "加薪 " 
                 << req.getSalary() << " GM通过"
                 << endl;
        }else{
            sendRequestTONextHandler(req);
        }
    }
};


void test(){
    unique_ptr<SalaryApprover> dm(new DM());
    unique_ptr<SalaryApprover> cto(new CTO());
    unique_ptr<SalaryApprover> gm(new GM());

    RaiseRequest zhangsan("张三", 800);
    RaiseRequest lisi("李四", 4500);
    RaiseRequest wangwu("王五", 13500);
    RaiseRequest shiwan("二万", 20000);

    dm->setNestChain(cto.get());
    cto->setNestChain(gm.get());
    gm->setNestChain(nullptr);

    dm->processRequest(zhangsan);
    dm->processRequest(lisi);
    dm->processRequest(wangwu);
    dm->processRequest(shiwan);

}

int main()
{
    test();
    return 0;
}

